package org.xmx0632.flywayside.handler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.maven.plugin.MojoExecutionException;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.internal.util.logging.Log;
import org.flywaydb.core.internal.util.logging.LogFactory;
import org.xmx0632.flywayside.FlywaySideUsageMojo;
import org.xmx0632.flywayside.constant.ModelEnum;
import org.xmx0632.flywayside.param.FlywayParam;
import org.xmx0632.flywayside.param.FlywaySideParams;
import org.xmx0632.flywayside.param.IndexParam;
import org.xmx0632.flywayside.utils.GlobalTableReplaceHolderMap;
import org.xmx0632.flywayside.utils.Helper;

/**
 * @author xmx0632
 * 
 * Created by xmx0632 on 2017/10/6.
 */
public abstract class BaseHandler {

	private static final int INSTANCE_PARAMETER_ELEMENT_NUMBER = 2;

	private static final Log LOG = LogFactory.getLog(Flyway.class);

	protected FlywaySideUsageMojo helper = new FlywaySideUsageMojo();

	protected FlywaySideParams flywaySideParams;

	protected String command;

	protected ModelEnum modelEnum;

	public BaseHandler(FlywaySideParams flywaySideParams) {
		this.flywaySideParams = flywaySideParams;
	}
	
	/**
	 * 计算表格数目
	 * 
	 * @return
	 */
	protected abstract Integer getTotalTableNumber();

	/**
	 * 计算当前表格索引号,数据库索引,实例索引
	 * 
	 * @param totalTableNumber
	 * @param i
	 * @return
	 */
	protected abstract IndexParam getIndexParam(int totalTableNumber, int i);

	/**
	 * 校验配置参数是否正确
	 * 
	 * @param totalTableNumber
	 * @param flywaySideParams
	 * @throws MojoExecutionException
	 */
	protected abstract void validateParameters(int totalTableNumber, FlywaySideParams flywaySideParams)
			throws MojoExecutionException;

	/**
	 * 如果配置文件中未配置,则用"前缀+序号"填充dblist和tableList
	 * 
	 * @param flywaySideParams
	 * @return
	 */
	protected abstract FlywaySideParams fillDbAndTableListIfNotConfiged(FlywaySideParams flywaySideParams);

	/**
	 * 打印使用方式
	 */
	protected abstract void printUsage();

	public Log getLog() {
		return LOG;
	}

	public List<FlywayParam> handle() throws MojoExecutionException {

		int totalTableNumber = getTotalTableNumber();
		getLog().info("totalTableNumber:" + totalTableNumber);

		validateParameters(totalTableNumber, flywaySideParams);

		flywaySideParams = fillDbAndTableListIfNotConfiged(flywaySideParams);

		printUsage();

		return getFlywayParams(totalTableNumber, command);
	}

	private List<FlywayParam> getFlywayParams(int totalTableNumber, String command) throws MojoExecutionException {
		List<FlywayParam> flywayParams = new ArrayList<FlywayParam>();

		for (int currTableIndex = 0; currTableIndex < totalTableNumber; currTableIndex++) {
			FlywayParam flywayParam = getFlywayParam(totalTableNumber, currTableIndex, command);
			flywayParams.add(flywayParam);
		}
		return flywayParams;
	}

	private FlywayParam getFlywayParam(int totalTableNumber, int currTableIndex, String command)
			throws MojoExecutionException {
		getLog().debug("*** totalTableNumber:" + totalTableNumber + ", currTableIndex:" + currTableIndex);
		IndexParam indexParam = getIndexParam(totalTableNumber, currTableIndex);
		int tableIndex = indexParam.getTableIndex();
		int dbIndex = indexParam.getDbIndex();
		int instIndex = indexParam.getInstIndex();

		String paddingTableIndex = formatPaddingIndex(flywaySideParams, tableIndex);

		// TODO 打印列表
		getLog().info(
				paddingTableIndex + " tableIndex:" + tableIndex + " dbIndex:" + dbIndex + " instIndex:" + instIndex);

		List<String> instanceList = flywaySideParams.getInstanceList();
		getLog().debug("instanceList size:" + instanceList.size());
		String instance = instanceList.get(instIndex);
		getLog().debug("instance:" + instance);
		String[] instanceInfo = instance.split("\\|");
		if (instanceInfo.length < INSTANCE_PARAMETER_ELEMENT_NUMBER) {
			getLog().error("config error! instance info format error! instance:" + instance);
			throw new MojoExecutionException("config error! instance info format error!");
		}
		String url = instanceInfo[0];
		String user = instanceInfo[1];
		String password = instanceInfo.length >= 3 ? instanceInfo[2] : "";

		getLog().debug("url:" + url + " user:" + user + " password:" + password);
		String dbName = flywaySideParams.getDbList().get(dbIndex);
		getLog().debug("dbName:" + dbName);

		// TODO 根据不同dbIndex获取对应的tableMapping
		Map<String, Map<String, String>> allPlaceHoldersMap = GlobalTableReplaceHolderMap.Instance.getMap();
		Map<String, String> placeHoldersMap = allPlaceHoldersMap
				.get(GlobalTableReplaceHolderMap.getKey(instIndex, dbIndex));
		return new FlywayParam(new String[] { flywaySideParams.getLocation() }, dbName, url, user, password,
				placeHoldersMap, command);
	}

	protected boolean isNotEmpty(List<String> instanceList) {
		return instanceList != null && instanceList.size() != 0;
	}

	protected boolean isEmpty(List<String> instanceList) {
		return !isNotEmpty(instanceList);
	}

	protected String formatPaddingIndex(FlywaySideParams flywaySideParams, int tableIndex) {
		return Helper.formatPaddingIndex(tableIndex, flywaySideParams.getTablePaddingNumber());
	}
}
